#include "./HttpServer.h"
#include "./HttpRequest.h"
#include "./HttpContext.h"
#include "./HttpResponse.h"

HttpServer::HttpServer(EventLoop *loop,
                       const InetAddress &listenAddr,
                       TcpServer::ListenOption listenOpt,
                       const std::string &threadName)
    : tcpServer_(loop, listenAddr, listenOpt, threadName),
      httpCallback_(std::move(defaultHttpCallback))
{
    this->tcpServer_.setThreadNum(3);

    // this->tcpServer_.setConnectionCallback(
    //     std::bind(&HttpServer::onConnectionCallback, this, std::placeholders::_1));
    // this->tcpServer_.setReadWriteCallback(
    //     std::bind(&HttpServer::onReadWriteCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
    this->tcpServer_.setConnectionCallback(
        [this](const TcpConnectionPtr &conn)
        {
            this->onConnectionCallback(conn);
        });
    this->tcpServer_.setReadWriteCallback(
        [this](const TcpConnectionPtr &conn, Buffer *buf, Timestamp receiveTime)
        {
            this->onReadWriteCallback(conn, buf, receiveTime);
        });
}

void HttpServer::defaultHttpCallback(const HttpRequest &requestuest, HttpResponse *response)
{
    response->setStatusCode(HttpResponse::StatusCode::NotFound404);
    response->setStatusMessage("Not Found");
    response->setNeedCloseConnection(true);
}

void HttpServer::onConnectionCallback(const TcpConnectionPtr &conn)
{
    if (conn->isConnected())
    {
        LOG_INFO("new Connection arrived");
    }
    else
    {
        LOG_INFO("Connection closed");
    }
}

void HttpServer::onReadWriteCallback(const TcpConnectionPtr &conn, Buffer *buf, Timestamp receiveTime)
{
    LOG_INFO("onReadWriteCallback");
    std::unique_ptr<HttpContext> context(new HttpContext);

    std::string requestuestMessage = "Request Data: \n";
    requestuestMessage += buf->getAllReadableDataDebug();
    LOG_DEBUG(requestuestMessage.c_str());

    // 解析请求
    bool isOk = context->parseRequest(buf, receiveTime);
    if (!isOk)
    {
        LOG_INFO("parseRequest failed!");
        conn->sendData("HTTP/1.1 400 Bad Request\r\n\r\n");
        conn->shutdown();
    }

    if (context->isRequestParseStateGotAll()) // 二次校验
    {
        LOG_INFO("parseRequest success!");
        this->handleRequest(conn, context->getRequest());
        context->reset();
    }
}

void HttpServer::handleRequest(const TcpConnectionPtr &conn, const HttpRequest &request)
{
    std::string connection = request.getHeader("Connection");
    bool needClose = connection == "close" ||
                     (request.getVersion() == HttpRequest::Version::Http10 && connection != "Keep-Alive"); // 短连接

    // 响应
    HttpResponse response(needClose);

    this->httpCallback_(request, &response); // 服务端回调填充响应体
    Buffer buf{};
    response.appendToBuffer(&buf); // 填充响应行和响应头

    conn->sendData(&buf);
    if (response.getNeedCloseConnection())
    {
        conn->shutdown();
    }
}

void HttpServer::start()
{
    LOG_INFO("HttpServer[%s] starts listening on %s...",
             this->tcpServer_.getName().c_str(), this->tcpServer_.getIpPort().c_str());
    this->tcpServer_.start();
}